package com.tj.bo.user.server;

import com.alibaba.fastjson.JSONObject;
import com.fqgj.common.utils.DES;
import com.fqgj.common.utils.DateUtil;
import com.fqgj.exception.common.ApplicationException;
import com.tj.bo.common.conf.enums.InvitationTypeEnum;
import com.tj.bo.common.conf.util.SerialNumberUtil;
import com.tj.bo.common.conf.util.ShareCodeUtils;
import com.tj.bo.user.client.UserRegisterService;
import com.tj.bo.user.client.enums.UserRealFlagEnum;
import com.tj.bo.user.client.enums.UserRegisterTypeEnum;
import com.tj.bo.user.client.vo.input.*;
import com.tj.bo.user.client.vo.output.UserRegisterOutput;
import com.tj.bo.user.server.entity.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * Created with IntelliJ IDEA.
 * User: binary
 * Date: 2020/6/10
 * Time: 下午3:42
 */
@Service
public class UserRegisterServiceImpl extends UserBaseService implements UserRegisterService {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserRegisterServiceImpl.class);


    private String getToken() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    private Date getExpireDate() {
        return DateUtil.addDate(new Date(), 30);
    }

    private Date getDemoExpireDate() {
        return DateUtil.getDate("2099-01-01", "yyyy-MM-dd");
    }

    @Transactional
    @Override
    public UserRegisterOutput deviceRegister(UserRegisterInput userRegisterInput) {
        String customerCode = SerialNumberUtil.getBizOrderNumber("C", "C");
        String userCodeDemo = SerialNumberUtil.getBizOrderNumber("U", "C");
        UserEntity userEntity = new UserEntity();
        userEntity.setCustomerCode(customerCode);
        userEntity.setUserCode(userCodeDemo);
        userEntity.setMobile("");
        userEntity.setName("");
        userEntity.setIdentityNo("");
        userEntity.setAppCode(userRegisterInput.getAppCode());

        UserAccessEntity userAccessEntityDemo = new UserAccessEntity();
        userAccessEntityDemo.setUserCode(userCodeDemo);
        userAccessEntityDemo.setUserAccount("12-345-6789");
        userAccessEntityDemo.setLoginNumber(userRegisterInput.getDeviceId());
        userAccessEntityDemo.setEmail("");
        userAccessEntityDemo.setOpenId("");
        userAccessEntityDemo.setDeviceId(userRegisterInput.getDeviceId());
        userAccessEntityDemo.setMobile("");
        userAccessEntityDemo.setPassWord("");
        userAccessEntityDemo.setToken(getToken());
        userAccessEntityDemo.setExpireDate(getDemoExpireDate());
        userAccessEntityDemo.setRealFlag(UserRealFlagEnum.DEMO.getType());
        userAccessEntityDemo.setAvatar("");
        userAccessEntityDemo.setNickname("");
        userAccessEntityDemo.setAppCode(userRegisterInput.getAppCode());
        userAccessEntityDemo.setPackageName(userRegisterInput.getPackageName());
        userAccessEntityDemo.setCustomerCode(customerCode);
        userAccessEntityDemo.setRegisterType(userRegisterInput.getUserRegisterTypeEnum().getType());
        userAccessEntityDemo.setChannel(userRegisterInput.getChannel());

        UserBehaviorRegisterEntity userBehaviorRegisterEntity = new UserBehaviorRegisterEntity();
        userBehaviorRegisterEntity.setUserCode(userCodeDemo);
        userBehaviorRegisterEntity.setDeviceId(userRegisterInput.getDeviceId());
        userBehaviorRegisterEntity.setClientId(userRegisterInput.getClientId());
        userBehaviorRegisterEntity.setPlatform(userRegisterInput.getPlatform());
        userBehaviorRegisterEntity.setVersion(userRegisterInput.getVersion());
        userBehaviorRegisterEntity.setVersionCode(userRegisterInput.getVersionCode());
        userBehaviorRegisterEntity.setChannel(userRegisterInput.getChannel());
        userBehaviorRegisterEntity.setAppCode(userRegisterInput.getAppCode());
        userBehaviorRegisterEntity.setPackageName(userRegisterInput.getPackageName());
        userBehaviorRegisterEntity.setIp(userRegisterInput.getIp());

        UserBehaviorDeviceEntity userBehaviorDeviceEntity = new UserBehaviorDeviceEntity();
        userBehaviorDeviceEntity.setUserCode(userCodeDemo);
        userBehaviorDeviceEntity.setDeviceId(userRegisterInput.getDeviceId());
        userBehaviorDeviceEntity.setClientId(userRegisterInput.getClientId());
        userBehaviorDeviceEntity.setPlatform(userRegisterInput.getPlatform());
        userBehaviorDeviceEntity.setVersion(userRegisterInput.getVersion());
        userBehaviorDeviceEntity.setVersionCode(userRegisterInput.getVersionCode());

        userDao.insert(userEntity);
        userAccessDao.insert(userAccessEntityDemo);
        userBehaviorRegisterDao.insert(userBehaviorRegisterEntity);
        userBehaviorDeviceDao.insert(userBehaviorDeviceEntity);

        return new UserRegisterOutput().setRealUserCode("")
                .setRealToken("")
                .setDemoUserCode(userAccessEntityDemo.getUserCode())
                .setDemoToken(userAccessEntityDemo.getToken());
    }

    @Transactional
    @Override
    public UserRegisterOutput emailRegister(UserRegisterInput userRegisterInput) {
        String password = null;
        try {
            password = DES.encrypt(userRegisterInput.getPassword());
        } catch (Exception e) {
            password = userRegisterInput.getPassword();
        }
        String loginAccount = "";
        if(Objects.equals(userRegisterInput.getUserRegisterTypeEnum(),UserRegisterTypeEnum.MOBILE)){
            loginAccount = userRegisterInput.getMobile();
        }else if(Objects.equals(userRegisterInput.getUserRegisterTypeEnum(),UserRegisterTypeEnum.EMAIL)){
            loginAccount = userRegisterInput.getEmail();
        }

        String customerCode = SerialNumberUtil.getBizOrderNumber("C", "C");
        String userCodeReal = SerialNumberUtil.getBizOrderNumber("U", "C");
        UserEntity userEntity = new UserEntity();
        userEntity.setCustomerCode(customerCode);
        userEntity.setUserCode(userCodeReal);
        userEntity.setMobile(userRegisterInput.getMobile());
        userEntity.setName("");
        userEntity.setIdentityNo("");
        userEntity.setAppCode(userRegisterInput.getAppCode());

        UserAccessEntity userAccessEntityReal = new UserAccessEntity();
        userAccessEntityReal.setUserCode(userCodeReal);
        userAccessEntityReal.setUserAccount("12-345-6789");
        userAccessEntityReal.setLoginNumber(loginAccount);
        userAccessEntityReal.setEmail(userRegisterInput.getEmail());
        userAccessEntityReal.setOpenId("");
        userAccessEntityReal.setDeviceId(userRegisterInput.getDeviceId());
        userAccessEntityReal.setMobile(userRegisterInput.getMobile());
        userAccessEntityReal.setPassWord(password);
        userAccessEntityReal.setToken(getToken());
        userAccessEntityReal.setExpireDate(getExpireDate());
        userAccessEntityReal.setRealFlag(UserRealFlagEnum.REAL.getType());
        userAccessEntityReal.setAvatar("");
        userAccessEntityReal.setNickname("");
        userAccessEntityReal.setAppCode(userRegisterInput.getAppCode());
        userAccessEntityReal.setPackageName(userRegisterInput.getPackageName());
        userAccessEntityReal.setCustomerCode(customerCode);
        userAccessEntityReal.setRegisterType(userRegisterInput.getUserRegisterTypeEnum().getType());
        userAccessEntityReal.setChannel(userRegisterInput.getChannel());

        UserAccessEntity userAccessEntityDemo = new UserAccessEntity();
        BeanUtils.copyProperties(userAccessEntityReal, userAccessEntityDemo);
        userAccessEntityDemo.setUserCode(SerialNumberUtil.getBizOrderNumber("U", "C"))
                .setToken(getToken())
                .setExpireDate(getDemoExpireDate())
                .setRealFlag(UserRealFlagEnum.DEMO.getType());

        UserBehaviorRegisterEntity userBehaviorRegisterEntity = new UserBehaviorRegisterEntity();
        userBehaviorRegisterEntity.setUserCode(userCodeReal);
        userBehaviorRegisterEntity.setDeviceId(userRegisterInput.getDeviceId());
        userBehaviorRegisterEntity.setClientId(userRegisterInput.getClientId());
        userBehaviorRegisterEntity.setPlatform(userRegisterInput.getPlatform());
        userBehaviorRegisterEntity.setVersion(userRegisterInput.getVersion());
        userBehaviorRegisterEntity.setVersionCode(userRegisterInput.getVersionCode());
        userBehaviorRegisterEntity.setChannel(userRegisterInput.getChannel());
        userBehaviorRegisterEntity.setAppCode(userRegisterInput.getAppCode());
        userBehaviorRegisterEntity.setPackageName(userRegisterInput.getPackageName());
        userBehaviorRegisterEntity.setIp(userRegisterInput.getIp());

        UserBehaviorDeviceEntity userBehaviorDeviceEntity = new UserBehaviorDeviceEntity();
        userBehaviorDeviceEntity.setUserCode(userCodeReal);
        userBehaviorDeviceEntity.setDeviceId(userRegisterInput.getDeviceId());
        userBehaviorDeviceEntity.setClientId(userRegisterInput.getClientId());
        userBehaviorDeviceEntity.setPlatform(userRegisterInput.getPlatform());
        userBehaviorDeviceEntity.setVersion(userRegisterInput.getVersion());
        userBehaviorDeviceEntity.setVersionCode(userRegisterInput.getVersionCode());

        userDao.insert(userEntity);
        userAccessDao.insert(userAccessEntityReal);
        userAccessDao.insert(userAccessEntityDemo);
        userBehaviorRegisterDao.insert(userBehaviorRegisterEntity);
        userBehaviorDeviceDao.insert(userBehaviorDeviceEntity);

        this.savePromotionMapping(userAccessEntityReal.getUserCode(), loginAccount, null);

        return inviteUserRegister(userRegisterInput, userAccessEntityReal, userAccessEntityDemo);
    }

    private void savePromotionMapping(String userCode, String loginAccount, String openId) {
        UserAccessEntity entity = userAccessDao.selectUserAccessByUserCode(userCode);
        UserPromotionMappingInfoEntity userPromotionMappingInfoEntity = new UserPromotionMappingInfoEntity();
        userPromotionMappingInfoEntity.setUserId(entity.getId());
        userPromotionMappingInfoEntity.setUserCode(entity.getUserCode());
        userPromotionMappingInfoEntity.setInvitationCode(ShareCodeUtils.idToCode(entity.getId()));
        userPromotionMappingInfoEntity.setInvitationType(InvitationTypeEnum.INVITE_FRIENDS.getCode());
        userPromotionMappingInfoEntity.setTotalBonus(0);
        userPromotionMappingInfoEntity.setTotalInvitePeople(0);
        if(StringUtils.isNotEmpty(loginAccount)){
            userPromotionMappingInfoEntity.setLoginAccount(loginAccount);
        }else if(StringUtils.isNotEmpty(openId)){
            userPromotionMappingInfoEntity.setLoginAccount(openId);
        }else{
            userPromotionMappingInfoEntity.setLoginAccount(loginAccount);
        }
        userPromotionMappingInfoDao.insert(userPromotionMappingInfoEntity);
        LOGGER.info("=========== user register userPromotionMappingInfoEntity:{} =============", JSONObject.toJSONString(userPromotionMappingInfoEntity));
    }

    private UserRegisterOutput inviteUserRegister(UserRegisterInput userRegisterInput, UserAccessEntity userAccessEntityReal, UserAccessEntity userAccessEntityDemo) {
        if(StringUtils.isNotEmpty(userRegisterInput.getInviteCode())){
            UserPromotionMappingInfoEntity entity = userPromotionMappingInfoDao.queryUserPromotionInfoByUserId(ShareCodeUtils.codeToId(userRegisterInput.getInviteCode()));
            if(entity != null){
                //邀请人数+1
                entity.setTotalInvitePeople(entity.getTotalInvitePeople() + 1);
                userPromotionMappingInfoDao.updateByPrimaryKey(entity);
                UserPromotionRecordEntity userPromotionRecordEntity = new UserPromotionRecordEntity();
                userPromotionRecordEntity.setUserCode(entity.getUserCode());
                userPromotionRecordEntity.setInvitedUserCode(userAccessEntityReal.getUserCode());
                userPromotionRecordEntity.setInvitationCode(entity.getInvitationCode());
                userPromotionRecordEntity.setInvitationType(entity.getInvitationType());
                userPromotionRecordEntity.setInvitedRegisterDate(new Date());
                userPromotionRecordEntity.setInvitedName(userAccessEntityReal.getLoginNumber());
                userPromotionRecordEntity.setBonus(0);
                userPromotionRecordEntity.setStatus(0);
                userPromotionRecordDao.insert(userPromotionRecordEntity);
            }
        }

        return new UserRegisterOutput().setRealUserCode(userAccessEntityReal.getUserCode())
                .setRealToken(userAccessEntityReal.getToken())
                .setDemoUserCode(userAccessEntityDemo.getUserCode())
                .setDemoToken(userAccessEntityDemo.getToken());
    }

    @Transactional
    @Override
    public UserRegisterOutput openIdRegister(UserRegisterInput userRegisterInput) {
        String customerCode = SerialNumberUtil.getBizOrderNumber("C", "C");
        String userCodeReal = SerialNumberUtil.getBizOrderNumber("U", "C");
        UserEntity userEntity = new UserEntity();
        userEntity.setCustomerCode(customerCode);
        userEntity.setUserCode(userCodeReal);
        userEntity.setMobile(StringUtils.isNotEmpty(userRegisterInput.getMobile()) ? userRegisterInput.getMobile() : "");
        userEntity.setName("");
        userEntity.setIdentityNo("");
        userEntity.setAppCode(userRegisterInput.getAppCode());

        UserAccessEntity userAccessEntityReal = new UserAccessEntity();
        userAccessEntityReal.setUserCode(userCodeReal);
        userAccessEntityReal.setUserAccount("12-345-6789");
        userAccessEntityReal.setLoginNumber(userRegisterInput.getOpenId());
        userAccessEntityReal.setEmail(userRegisterInput.getEmail());
        userAccessEntityReal.setOpenId(userRegisterInput.getOpenId());
        userAccessEntityReal.setDeviceId(userRegisterInput.getDeviceId());
        userAccessEntityReal.setMobile(StringUtils.isNotEmpty(userRegisterInput.getMobile()) ? userRegisterInput.getMobile() : "");
        userAccessEntityReal.setPassWord("");
        userAccessEntityReal.setToken(getToken());
        userAccessEntityReal.setExpireDate(getExpireDate());
        userAccessEntityReal.setRealFlag(UserRealFlagEnum.REAL.getType());
        userAccessEntityReal.setAvatar("");
        userAccessEntityReal.setNickname(userRegisterInput.getNickname());
        userAccessEntityReal.setAppCode(userRegisterInput.getAppCode());
        userAccessEntityReal.setPackageName(userRegisterInput.getPackageName());
        userAccessEntityReal.setCustomerCode(customerCode);
        userAccessEntityReal.setRegisterType(userRegisterInput.getUserRegisterTypeEnum().getType());
        userAccessEntityReal.setChannel(userRegisterInput.getChannel());
        userAccessEntityReal.setUserName(StringUtils.isNotBlank(userRegisterInput.getNickname()) ? userRegisterInput.getNickname() : "");

        UserAccessEntity userAccessEntityDemo = new UserAccessEntity();
        BeanUtils.copyProperties(userAccessEntityReal, userAccessEntityDemo);
        userAccessEntityDemo.setUserCode(SerialNumberUtil.getBizOrderNumber("U", "C"))
                .setToken(getToken())
                .setExpireDate(getDemoExpireDate())
                .setRealFlag(UserRealFlagEnum.DEMO.getType());

        UserBehaviorRegisterEntity userBehaviorRegisterEntity = new UserBehaviorRegisterEntity();
        userBehaviorRegisterEntity.setUserCode(userCodeReal);
        userBehaviorRegisterEntity.setDeviceId(userRegisterInput.getDeviceId());
        userBehaviorRegisterEntity.setClientId(userRegisterInput.getClientId());
        userBehaviorRegisterEntity.setPlatform(userRegisterInput.getPlatform());
        userBehaviorRegisterEntity.setVersion(userRegisterInput.getVersion());
        userBehaviorRegisterEntity.setVersionCode(userRegisterInput.getVersionCode());
        userBehaviorRegisterEntity.setChannel(userRegisterInput.getChannel());
        userBehaviorRegisterEntity.setAppCode(userRegisterInput.getAppCode());
        userBehaviorRegisterEntity.setPackageName(userRegisterInput.getPackageName());
        userBehaviorRegisterEntity.setIp(userRegisterInput.getIp());

        UserBehaviorDeviceEntity userBehaviorDeviceEntity = new UserBehaviorDeviceEntity();
        userBehaviorDeviceEntity.setUserCode(userCodeReal);
        userBehaviorDeviceEntity.setDeviceId(userRegisterInput.getDeviceId());
        userBehaviorDeviceEntity.setClientId(userRegisterInput.getClientId());
        userBehaviorDeviceEntity.setPlatform(userRegisterInput.getPlatform());
        userBehaviorDeviceEntity.setVersion(userRegisterInput.getVersion());
        userBehaviorDeviceEntity.setVersionCode(userRegisterInput.getVersionCode());

        UserThirdPartEntity userThirdPartEntity = new UserThirdPartEntity();
        userThirdPartEntity.setOpenId(userRegisterInput.getOpenId());
        userThirdPartEntity.setUserCode(userCodeReal);
        userThirdPartEntity.setRegisterType(userRegisterInput.getUserRegisterTypeEnum().getType());

        userDao.insert(userEntity);
        userAccessDao.insert(userAccessEntityReal);
        userAccessDao.insert(userAccessEntityDemo);
        userBehaviorRegisterDao.insert(userBehaviorRegisterEntity);
        userBehaviorDeviceDao.insert(userBehaviorDeviceEntity);
        userThirdPartDao.insert(userThirdPartEntity);

        this.savePromotionMapping(userAccessEntityReal.getUserCode(), null, userRegisterInput.getOpenId());

        return inviteUserRegister(userRegisterInput, userAccessEntityReal, userAccessEntityDemo);
    }

    @Override
    public void resetPassword(UserResetPasswordInput userResetPasswordInput) {
        if (StringUtils.isEmpty(userResetPasswordInput.getAppCode())
                || StringUtils.isEmpty(userResetPasswordInput.getEmail())
                || StringUtils.isEmpty(userResetPasswordInput.getPassword())) {
            throw new ApplicationException("Parameter error");
        }
        String password = null;
        try {
            password = DES.encrypt(userResetPasswordInput.getPassword());
        } catch (Exception e) {
            password = userResetPasswordInput.getPassword();
        }

        UserAccessEntity entityReal = userAccessDao.selectUserAccessByAppCodeAndEmail(userResetPasswordInput.getAppCode(), UserRealFlagEnum.REAL.getType(), userResetPasswordInput.getEmail());
        entityReal.setPassWord(password);

        UserAccessEntity entityDemo = userAccessDao.selectUserAccessByAppCodeAndEmail(userResetPasswordInput.getAppCode(), UserRealFlagEnum.DEMO.getType(), userResetPasswordInput.getEmail());
        entityDemo.setPassWord(password);
        userAccessDao.updateByPrimaryKey(entityReal);
        userAccessDao.updateByPrimaryKey(entityDemo);
    }

    @Override
    public void registerChannelRepair(UserChannelRepairInput userChannelRepairInput) {
        if (StringUtils.isEmpty(userChannelRepairInput.getAppCode())
                || StringUtils.isEmpty(userChannelRepairInput.getDeviceId())) {
            return;
        }
        String invalidChannel = "TD";
        if (StringUtils.isEmpty(userChannelRepairInput.getChannel())
                || invalidChannel.equals(userChannelRepairInput.getChannel())) {
            LOGGER.info("无效渠道不执行更新,deviceId:{},channel:{},userCode:{}", userChannelRepairInput.getDeviceId(), userChannelRepairInput.getChannel(), userChannelRepairInput.getUserCode());
            return;
        }

        List<UserAccessEntity> userAccessEntityList = userAccessDao.selectUserAccessByDeviceId(userChannelRepairInput.getAppCode(), userChannelRepairInput.getDeviceId(), invalidChannel);
        if (userAccessEntityList == null || userAccessEntityList.size() == 0) {
            return;
        }
        for (UserAccessEntity entity : userAccessEntityList) {
            UserAccessEntity upEntity = new UserAccessEntity();
            upEntity.setId(entity.getId());
            upEntity.setChannel(userChannelRepairInput.getChannel());
            userAccessDao.updateByPrimaryKey(upEntity);

            UserBehaviorRegisterEntity userBehaviorRegisterEntity = userBehaviorRegisterDao.selectUserBehaviorRegisterByUserCode(entity.getUserCode());
            if (userBehaviorRegisterEntity != null) {
                UserBehaviorRegisterEntity userBehaviorRegisterEntity2 = new UserBehaviorRegisterEntity();
                userBehaviorRegisterEntity2.setId(userBehaviorRegisterEntity.getId());
                userBehaviorRegisterEntity2.setChannel(userChannelRepairInput.getChannel());
                userBehaviorRegisterDao.updateByPrimaryKey(userBehaviorRegisterEntity2);
            }

            LOGGER.info("渠道更新成功,msg:{},targetUserCode:{},deviceId:{},channel:{},userCode:{}", userChannelRepairInput.getMessage(), entity.getUserCode(), userChannelRepairInput.getDeviceId(), userChannelRepairInput.getChannel(), userChannelRepairInput.getUserCode());
        }
    }

    @Override
    @Async
    public void registerChannelRepairAsync(UserChannelRepairInput userChannelRepairInput) {
        this.registerChannelRepair(userChannelRepairInput);
    }

    @Override
    public boolean userAuthentication(UserAuthenticationRO userAuthentication) {
        UserAccessEntity entity = userAccessDao.selectUserAccessByUserCode(userAuthentication.getUserCode());
        if(entity != null){
            entity.setEmail(userAuthentication.getEmail());
            entity.setMobile(userAuthentication.getMobile());
            entity.setUserName(userAuthentication.getUserName());
            entity.setIsAuthentication(1);
            userAccessDao.updateByPrimaryKey(entity);

            UserEntity userEntity = userDao.selectByUserCode(userAuthentication.getUserCode());
            if(userEntity != null){
                userEntity.setMobile(userAuthentication.getMobile());
                userEntity.setName(userAuthentication.getUserName());
                userDao.updateByPrimaryKey(userEntity);
            }
        }
        return false;
    }

    @Override
    public void updateUserAccess(UserAccessUpdateRO userAccessUpdateRO) {
        UserAccessEntity entity = userAccessDao.selectUserAccessByUserCode(userAccessUpdateRO.getUserCode());
        if((entity != null && entity.getIsAuthentication() == 0)
                || (StringUtils.isBlank(entity.getUserName()) || StringUtils.isBlank(entity.getEmail()) || StringUtils.isBlank(entity.getMobile()))){
            entity.setUserName(userAccessUpdateRO.getName());
            entity.setMobile(userAccessUpdateRO.getMobile());
            entity.setEmail(userAccessUpdateRO.getEmail());
            entity.setIsAuthentication(1);
            userAccessDao.updateByPrimaryKey(entity);
        }
    }
}
